home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
ObjectTable.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-16
|
7KB
|
353 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "ObjectTable.h"
#include "Class.h"
#include "OrdColl.h"
#include "Set.h"
#include "System.h"
#include "Error.h"
#include "ClassManager.h"
#include "String.h"
#include "CmdNo.h"
#include "Math.h"
ObjectTable *gObjectTable;
extern void ETCleanup();
static bool rlock;
static int lasts;
//---- ObjectTable -------------------------------------------------------------
NewMetaImpl(ObjectTable,Object, (TVP(table,size), T(tally), TP(delayed)));
bool ObjectTable::died;
Object **ObjectTable::table;
int ObjectTable::size, ObjectTable::tally;
OrdCollection *ObjectTable::delayed, *ObjectTable::rdelayed;
int ObjectTable::iterlevel;
Class *ObjectTable::tab[300];
ObjectTable::ObjectTable()
{
if (gObjectTable)
Error("ObjectTable", "only one instance of ObjectTable");
size= Math::NextPrime(10000);
table= new Object* [size];
}
ObjectTable::~ObjectTable()
{
SafeDelete(delayed);
SafeDelete(rdelayed);
}
//---- static members --------------------------------------------------------
void ObjectTable::Add(Object *op)
{
static bool olock= FALSE;
if (op == 0) {
::Error("ObjectTable::Add", "op is 0");
return;
}
if (died || olock || op->TestFlag(cObjIsProto))
return;
if (gObjectTable == 0) {
olock= TRUE;
gObjectTable= new ObjectTable;
olock= FALSE;
Add(gObjectTable);
}
if (iterlevel > 0) {
if (delayed == 0) {
olock= TRUE;
delayed= new OrdCollection;
olock= FALSE;
}
delayed->Add(op);
} else {
table[FindElement(op)]= op;
tally++;
if (HighWaterMark())
Expand(2 * size);
}
}
void ObjectTable::Remove(Object *op)
{
if (op == 0)
::Error("ObjectTable::Remove", "remove 0 from ObjectTable");
if (/* died || */ op->TestFlag(cObjIsProto) || rlock)
return;
Stream::InvalidatePtr(op);
if (delayed && delayed->FindPtr(op)) {
delayed->RemovePtr(op);
return;
}
if (iterlevel > 0) {
if (rdelayed == 0) {
fprintf(stderr, "aha\n");
rdelayed= new OrdCollection;
}
rdelayed->Add(op);
return;
}
if (table == 0)
return;
int i= FindElement(op);
if (table[i] == 0 && !op->TestFlag(cObjIsProto)) {
::Warning("ObjectTable::Remove", "0x%08x not found at %d", (int)op, i);
for (int j= 0; j < size; j++) {
if (table[j] == op) {
::Error("ObjectTable::Remove", "%d found at %d !!!", (int)op, j);
i= j;
}
}
}
table[i]= 0;
FixCollisions(i);
tally--;
if (gClassManager) {
OrdCollection *col= gClassManager->GetClassTable();
int s= col->Size();
if (tab[0] == 0) {
if (s < lasts) {
Iter next(col);
register Class *cl;
for (int i= 0; cl= (Class*) next(); i++)
tab[i]= cl;
}
lasts= s;
}
if (s <= 0) {
Object *t= gClassManager;
gClassManager= 0;
delete t;
ETCleanup();
SafeDelete(gObjectTable);
InstanceStatistics();
died= TRUE;
SafeDelete(table);
Storage::FreeAll();
}
}
}
int ObjectTable::FindElement(Object *op)
{
register slot, n;
register Object *slotOp;
if (table == 0)
return 0;
slot= ((u_int) op >> 2) % size;
for (n= 0; n < size; n++) {
if ((slotOp= table[slot]) == 0)
break;
if (op == slotOp)
break;
if (++slot == size)
slot= 0;
}
return slot;
}
void ObjectTable::FixCollisions (int index)
{
register int oldIndex, nextIndex;
register Object *nextObject;
for (oldIndex= index+1; ;oldIndex++) {
if (oldIndex >= size)
oldIndex= 0;
nextObject= table[oldIndex];
if (nextObject == 0)
break;
nextIndex= FindElement(nextObject);
if (nextIndex != oldIndex) {
table[nextIndex]= nextObject;
table[oldIndex]= 0;
}
}
}
void ObjectTable::Expand(int newSize)
{
register int i;
register Object **oldTable= table, *op;
int oldsize= size;
newSize= Math::NextPrime(newSize);
table= new Object*[newSize];
size= newSize;
tally= 0;
for (i= 0; i < oldsize; i++)
if (op= oldTable[i])
Add(op);
delete oldTable;
}
void ObjectTable::HashStatistics()
{
}
void ObjectTable::InstanceStatistics()
{
int i, n, cum= 0;
if (tally == 0)
return;
for (i= 0; tab[i]; i++)
tab[i]->ResetInstanceCount();
{
register Object *op;
ObjectTableIter next(0);
while (op= next())
if (op->TestFlag(cObjNonDeleted))
op->IsA()->AddInstance();
else
fprintf(stderr, "oops 0x%08x\n", op);
}
fprintf(stderr, "\n");
fprintf(stderr, "instances still in ObjectTable\n");
fprintf(stderr, "class cnt size\n");
fprintf(stderr, "=====================================\n");
for (i= 0; tab[i]; i++) {
n= tab[i]->GetInstanceCount();
if (n > 0) {
fprintf(stderr, "%-20s %8d%8d\n", tab[i]->Name(), n, tab[i]->Size());
cum+= n;
}
}
fprintf(stderr, "-------------------------------------\n");
fprintf(stderr, "Total %8d\n", cum);
fprintf(stderr, "=====================================\n");
fprintf(stderr, "\n");
}
void ObjectTable::UpdateInstCount(bool heaponly)
{
register Object *op;
if (table == 0)
return;
gClassManager->GetClassTable()->ForEach(Class,ResetInstanceCount)();
ObjectTableIter next(0);
if (heaponly) {
while (op= next())
if (op->IsShared())
op->IsA()->AddInstance();
} else {
while (op= next())
op->IsA()->AddInstance();
}
}
void *ObjectTable::CheckPtrAndWarn(char *msg, void *vp)
{
if (table && vp && table[FindElement((Object*)vp)]) {
Remove((Object*)vp);
::Warning("ObjectTable::CheckPtrAndWarn", "%s (0x%08x)\n", msg, vp);
}
return vp;
}
Object *ObjectTable::SomeInstance(Class *cl)
{
register Object *op;
ObjectTableIter next(0);
while (op= next())
if (op->IsA()->isKindOf(cl))
break;
return op;
}
Object *ObjectTable::SomeMember(Class *cl)
{
register Object *op;
ObjectTableIter next(0);
while (op= next())
if (op->IsA() == cl)
break;
return op;
}
//---- ObjectTableIter ---------------------------------------------------------
ObjectTableIter::ObjectTableIter(Class *cl, bool mem)
{
ObjectTable::iterlevel++;
cursor= 0;
fromClass= cl;
members= mem;
}
ObjectTableIter::~ObjectTableIter()
{
--ObjectTable::iterlevel;
if (ObjectTable::iterlevel <= 0) {
register Object *op;
if (ObjectTable::delayed) {
Iter next(ObjectTable::delayed);
while (op= next())
ObjectTable::Add(op);
rlock= TRUE;
SafeDelete(ObjectTable::delayed);
rlock= FALSE;
}
if (ObjectTable::rdelayed) {
Iter next(ObjectTable::rdelayed);
while (op= next())
ObjectTable::Remove(op);
rlock= TRUE;
SafeDelete(ObjectTable::rdelayed);
rlock= FALSE;
}
}
}
Object *ObjectTableIter::operator()()
{
if (ObjectTable::table == 0)
return 0;
register Object *op, **t= ObjectTable::table;
int s= ObjectTable::size;
for ( ; cursor < s ; cursor++) {
if (op= t[cursor]) {
if (fromClass == 0)
break;
if (members && fromClass == op->IsA())
break;
if (!members && op->IsA()->isKindOf(fromClass))
break;
}
}
return cursor < s ? t[cursor++] : 0;
}
void gIsA(Object *op)
{
if (op == 0 || !ObjectTable::PtrIsValid(op))
return;
fprintf(stderr, "%s\n", op->ClassName());
return;
}